using Consul;
using Microsoft.Extensions.Configuration;
using System.Text.Json;

namespace WebApp8.Configuration
{
    public class ConsulConfigurationProvider : ConfigurationProvider
    {
        private readonly string _consulUrl;
        private readonly string _configPath;
        private readonly IConsulClient _consulClient;

        public ConsulConfigurationProvider(string consulUrl, string configPath)
        {
            _consulUrl = consulUrl;
            _configPath = configPath;
            _consulClient = new ConsulClient(cfg =>
            {
                cfg.Address = new Uri(consulUrl);
            });
        }

        public override void Load()
        {
            LoadAsync().Wait();
        }

        private async Task LoadAsync()
        {
            try
            {
                var response = await _consulClient.KV.Get(_configPath);
                if (response?.Response == null)
                {
                    return;
                }

                var value = System.Text.Encoding.UTF8.GetString(response.Response.Value);
                var config = JsonSerializer.Deserialize<Dictionary<string, object>>(value);

                if (config != null)
                {
                    ProcessConfig("", config);
                }
            }
            catch (Exception ex)
            {
                // 如果无法从Consul获取配置，记录错误但不抛出异常
                Console.WriteLine($"Error loading configuration from Consul: {ex.Message}");
            }
        }

        private void ProcessConfig(string prefix, Dictionary<string, object> config)
        {
            foreach (var kvp in config)
            {
                var key = string.IsNullOrEmpty(prefix) ? kvp.Key : $"{prefix}:{kvp.Key}";
                
                if (kvp.Value is JsonElement jsonElement)
                {
                    switch (jsonElement.ValueKind)
                    {
                        case JsonValueKind.Object:
                            var nestedObject = JsonSerializer.Deserialize<Dictionary<string, object>>(
                                jsonElement.GetRawText());
                            if (nestedObject != null)
                            {
                                ProcessConfig(key, nestedObject);
                            }
                            break;
                        default:
                            Data[key] = jsonElement.GetRawText().Trim('"');
                            break;
                    }
                }
                else
                {
                    Data[key] = kvp.Value?.ToString() ?? "";
                }
            }
        }
    }

    public class ConsulConfigurationSource : IConfigurationSource
    {
        private readonly string _consulUrl;
        private readonly string _configPath;

        public ConsulConfigurationSource(string consulUrl, string configPath)
        {
            _consulUrl = consulUrl;
            _configPath = configPath;
        }

        public IConfigurationProvider Build(IConfigurationBuilder builder)
        {
            return new ConsulConfigurationProvider(_consulUrl, _configPath);
        }
    }

    public static class ConsulConfigurationExtensions
    {
        public static IConfigurationBuilder AddConsul(
            this IConfigurationBuilder builder,
            string consulUrl,
            string configPath)
        {
            return builder.Add(new ConsulConfigurationSource(consulUrl, configPath));
        }
    }
} 